package net.borderwars.webstartclient;

import net.borderwars.beans.Player;
import net.borderwars.beans.Robot;
import net.borderwars.jedit.JEditTextArea;
import net.borderwars.jedit.JavaTokenMarker;
import net.borderwars.userserver.ServerInterface;
import net.borderwars.util.GUIUtils;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.sql.SQLException;

/**
 * User: hubbard
 * Date: Aug 10, 2006
 * Time: 2:35:55 PM
 */
public class ClientFrame extends JFrame {
    private ServerInterface server;
    private DefaultMutableTreeNode root;
    private DefaultMutableTreeNode publicDomain = new DefaultMutableTreeNode ("Public");
    private DefaultMutableTreeNode authored = new DefaultMutableTreeNode ("Ours");
    private DefaultMutableTreeNode matches = new DefaultMutableTreeNode ("Matches");
    private OurTreeModel treeModel;
    private JSplitPane splitPane;
    private Robot selectedRobot = null;
    private JButton addCompileButton;
    private Player player;
    private JEditTextArea codeArea;
    private JFrame ourFrame;
    private JButton newBotButton;

    public ClientFrame (ServerInterface server) throws SQLException {
        super ("Borderwars Robot Editor");
        this.server = server;

        setSize (800, 600);
        GUIUtils.centerFrame (this, 800, 600);
        getContentPane ().setLayout (new BorderLayout ());
        splitPane = new JSplitPane ();
        add (splitPane, BorderLayout.CENTER);
        player = server.getPlayer ();
        root = new DefaultMutableTreeNode (player.getName ());
        JTree tree = setupTree ();
        splitPane.add (tree, JSplitPane.LEFT);
        splitPane.setDividerLocation (-1);
        addQuitListener ();
        ourFrame = this;
        setVisible (true);

    }

    private JTree setupTree () throws SQLException {
        treeModel = new OurTreeModel (root);
        JTree tree = new JTree (treeModel);
        root.add (publicDomain);
        root.add (authored);
        root.add (matches);

        for (Robot robot : server.getPublicRobots ()) {
            publicDomain.add (new DefaultMutableTreeNode (robot));
        }
        for (Robot robot : player.getWrote ()) {
            authored.add (new DefaultMutableTreeNode (robot));
        }

        addTreeListener (tree);

        int rc = tree.getRowCount () - 1;
        while (rc >= 0) {
            tree.expandRow (rc--);
        }
        tree.setSelectionRow (0);

        return (tree);
    }

    private JPanel getRobotPanel (Robot robot) {

        JPanel buttonBar = new JPanel (new FlowLayout ());
        JPanel p = new JPanel (new BorderLayout ());
        p.add (buttonBar, BorderLayout.SOUTH);

        addCompileButton (buttonBar);
        addQuitButton (buttonBar);
        addNewBotButton (buttonBar);
        addFightButton (buttonBar);
        codeArea = new JEditTextArea ();
        codeArea.setTokenMarker (new JavaTokenMarker ());
        codeArea.setText (robot.getSource ());
        codeArea.scrollTo (0, 0);

        p.add (codeArea, BorderLayout.CENTER);
        return (p);
    }

    private void addFightButton (final JPanel buttonBar) {
        JButton fightButton = new JButton ("Fight!");
        fightButton.addActionListener (new ActionListener() {
            public void actionPerformed (ActionEvent e) {
                final JDialog d = new JDialog (ourFrame, "Team 1 Selection", true);
                JPanel buttonBar = new JPanel (new FlowLayout ());
                d.setSize (384, 256);
                int x = ourFrame.getLocationOnScreen ().x + ourFrame.getWidth () / 2 - d.getWidth () / 2;
                int y = ourFrame.getLocationOnScreen ().y + ourFrame.getHeight () / 2 - d.getHeight () / 2;
                Point p = new Point (x, y);
                d.setLocation (p);
                JButton goButton = new JButton ("GO");
                buttonBar.add (goButton);
                JButton cancelButton = new JButton ("Cancel");
                buttonBar.add (cancelButton);
                d.getContentPane ().setLayout (new BorderLayout ());
                d.getContentPane ().add (buttonBar, BorderLayout.SOUTH);
                d.setVisible (true);

                cancelButton.addActionListener (new ActionListener() {
                    public void actionPerformed (ActionEvent e) {
                        d.dispose ();
                    }
                });

                goButton.addActionListener (new ActionListener() {
                    public void actionPerformed (ActionEvent e) {
                        doBattle ();
                    }
                });

            }
        });

        buttonBar.add (fightButton);

    }

    private void doBattle () {
        //To change body of created methods use File | Settings | File Templates.
    }

    private void addNewBotButton (final JPanel buttonBar) {
        newBotButton = new JButton ("New Robot");
        newBotButton.addActionListener (new ActionListener() {
            public void actionPerformed (ActionEvent e) {
                String name = JOptionPane.showInputDialog ("What is the Robots name?");
                Robot r = new Robot ();
                r.setName (name);
                r.setAuthor (player);
                r.setPublicDomain (false);

                try {
                    r = server.saveRobot (r);
                    authored.add (new DefaultMutableTreeNode (r));
                }
                catch (SQLException e1) {
                    e1.printStackTrace ();
                }
            }
        });
        buttonBar.add (newBotButton);
    }

    private void addCompileButton (final JPanel buttonBar) {
        addCompileButton = new JButton ("Compile");
        addCompileButton.addActionListener (new ActionListener() {
            public void actionPerformed (ActionEvent e) {
                selectedRobot.setSource (codeArea.getText ());
                try {
                    String results = server.compile (selectedRobot);
                    if (results.trim ().length () != 0) {
                        JOptionPane.showConfirmDialog (ourFrame, results);
                    }
                    else {
                        server.saveRobot (selectedRobot);
                    }
                }
                catch (IOException e1) {
                    e1.printStackTrace ();  //To change body of catch statement use File | Settings | File Templates.
                }
                catch (InterruptedException e1) {
                    e1.printStackTrace ();  //To change body of catch statement use File | Settings | File Templates.
                }
                catch (SQLException e1) {
                    e1.printStackTrace ();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        });
        buttonBar.add (addCompileButton);
    }

    private void addQuitButton (final JPanel buttonBar) {
        JButton quit = new JButton ("Quit");
        quit.addActionListener (new ActionListener() {
            public void actionPerformed (ActionEvent e) {
                System.exit (0);
            }
        });

        buttonBar.add (quit);
    }

    private void addTreeListener (final JTree tree) {
        tree.addTreeSelectionListener (new TreeSelectionListener() {
            public void valueChanged (TreeSelectionEvent e) {
                TreePath paths[] = tree.getSelectionPaths ();
                if (paths != null) { // tree changed.. so that nothing was selected
                    for (int i = 0; i < paths.length; i++) {
                        TreePath path = paths[i];
                        System.out.println ("selected: " + path);
                    }
                    if (paths.length == 1) { // if only one thing is selected
                        DefaultMutableTreeNode dmtn = (DefaultMutableTreeNode) paths[0].getLastPathComponent ();
                        if (dmtn.isLeaf ()) {
                            Object o = dmtn.getUserObject ();
                            if (o instanceof Robot) {
                                Robot robot = (Robot) o;
                                selectedRobot = robot;
                                splitPane.add (getRobotPanel (robot), JSplitPane.RIGHT);
                                addCompileButton.setEnabled (true);

                            }
                            else {
                                selectedRobot = null;
                                if (addCompileButton != null) // if they first click on a non robot.. then there won't be  a compile button yet
                                    addCompileButton.setEnabled (false);

                                splitPane.add (new JLabel ("No Robot Selected"), JSplitPane.RIGHT);
                            }
                        }
                    }
                }
            }
        });
    }

    private void addQuitListener () {
        addWindowListener (new WindowAdapter() {
            public void windowClosed (WindowEvent e) {
                System.exit (0);
            }
        });
    }

    private class OurTreeModel extends DefaultTreeModel {
        public OurTreeModel (final TreeNode root) {
            super (root);
        }
    }

}
